/******************************************************************************
//             INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in accordance with the terms of that agreement.
//    Copyright(c) 2000 - 2001 Intel Corporation. All Rights Reserved.
//
//  VSS: 
//     $Workfile: $
//     $Revision: $
//     $Date:     $
//     $Archive:  $
//
//  Description:
//      Intel(R) Integrated Performance Primitives - JPEG Helper file.
//      This file contains "BGR to YCbCr" conversion functions for encoding. 
//
//  History:
//     Date         Author        Changes
//     2000/5/20    Vivian Xiong  Created  (Version 0.1)
//     2001/2/12    Jerry Hu      Modified (Version 0.2, for MCU processing)
//
********************************************************************************/
#include "_ippjpeg.h"

/*
// The following routines implement the color conversion equations
// from CCIR Recommendation 601.
//
// In floating point notation, BGR->YCbCr:
//    Y  =  ( 0.29900*R) + (0.58700*G) + (0.11400*B) - 0.5
//    Cb = ((-0.16874*R) - (0.33126*G) + (0.50000*B))
//    Cr = (( 0.50000*R) - (0.41869*G) - (0.08131*B))
//
// In fixed point notation (using 10 bits), BGR->YCbCr:
//    Y  =  ((306*R) + (601*G) + (117*B)) / 1024 - 128
//       =  ((306*R) + (601*G) + (117*B) - 1024*128 + 512) >> 10
//       =  ((306*R) + (601*G) + (117*B) - 130560) >> 10
//
//    Cb =  ((-173*R) - (339*G) + (512*B)) / 1024
//       =  ((-173*R) - (339*G) + (B<<9) + 512) >> 10
//
//    Cr =  ((512*R) - (429*G) - (83*B)) / 1024
//       =  ((R<<9) - (429*G) - (83*B) + 512) >> 10
//
// Note: 1) A rounding technique for the right-shift operation is
//          incorporated directly into these fixed point equations
//          (i.e., a right-shift of N is preceded by adding 2^(N-1)).
//
//       2) A "level shift" of -128 is needed to set up for the forward DCT.  
//          This level shift has been incorporated directly 
//          into these fixed point equations.
*/

/* BGR->YCbCr */
#define _BGR2YCC_LS_Y(B, G, R)\
                     (((306 * (R)) + (601 * (G)) + (117 * (B)) - 130560) >> 10)

#define _BGR2YCC_LS_CB(B, G, R)\
                      (((-173 * (R)) - (339 * (G)) + ((B) << 9) + 512) >> 10)

#define _BGR2YCC_LS_CR(B, G, R)\
                      ((((R) << 9)  - (429 * (G)) - (83 * (B)) + 512) >> 10)


/*
// 4:2:2 Cb and Cr equations.  Note, the R, G, and B values are passed in
// accummulated, not averaged.  Thus, the CC constant is mulitiplied by 2,
// and the whole CC equation (prior to the -128 level shift) is divided by 2.
//    Cb =  ((-173*R) - (339*G) + (B<<9) + 512) >> 10
//       => ((-173*R) - (339*G) + (B<<9) + 1024) >> 11
//
//    Cr =  ((R<<9) - (429*G) - (83*B) + 512) >> 10
//       => ((R<<9) - (429*G) - (83*B) + 1024) >> 11
*/

/* BGR->YCbCr */
#define _BGR2YCC422_LS_CB(B, G, R)\
    (((-173*(R)) - (339*(G)) + ((B)<<9) + 1024) >> 11)

#define _BGR2YCC422_LS_CR(B, G, R)\
    ((((R)<<9)  - (429*(G)) - (83*(B)) + 1024) >> 11)

/*
// 4:1:1 Cb and Cr equations.  Note, the R, G, and B values are passed in
// accummulated, not averaged.  Thus, the CC constant is mulitiplied by 4,
// and the whole CC equation (prior to the -128 level shift) is divided by 4.
//    Cb =  ((-173*R) - (339*G) + (B<<9) + 512) >> 10
//       => ((-173*R) - (339*G) + (B<<9) + 2048) >> 12
//
//    Cr =  ((R<<9) - (429*G) - (83*B) + 512) >> 10
//       => ((R<<9) - (429*G) - (83*B) + 2048) >> 12
*/

/* BGR->YCbCr */
#define _BGR2YCC411_LS_CB(B, G, R)\
    (((-173*(R)) - (339*(G)) + ((B)<<9) + 2048) >> 12)

#define _BGR2YCC411_LS_CR(B, G, R)\
    ((((R)<<9)  - (429*(G)) - (83*(B)) + 2048) >> 12)


/******************************************************************************
// Name:             ippiBGRToYCbCr444LS_MCU_8u16s_C3P3
// Description:      Converts MCU from BGR to YCbCr444. The size is 8x8.
// Input Arguments: 
//          pSrcBGR: Identifies input image data buffer. It was sorted block by bock.
//          srcStep: Specifies the number of bytes in a line of the source image. 
//
// Output Arguments:
//       pDstMCU[3]: Identifies three pointer arrays. 
//                   pSrcMCU[0] point to Y  block.
//                   pSrcMCU[1] point to Cb block.
//                   pSrcMCU[2] point to Cr block.
//                  
// Remarks:      
//                   1. The start address of each "pDstMCU[]" shall be aligned at 4byte boundary.
//                   2. It is better to do this alignment at 32byte boundary to optimize 
//                      D-Cache accessing.
//                   
// Returns:         
//    IPP_STATUS_OK: Succeeds.
//
******************************************************************************/
IPPFUN(IppStatus, ippiBGRToYCbCr444LS_MCU_8u16s_C3P3)  (const Ipp8u * pSrcBGR, 
							                            int srcStep, 
       									                Ipp16s * pDstMCU[3])
{
    int j;
    Ipp16s * pDstMCUY;
    Ipp16s * pDstMCUCb;
    Ipp16s * pDstMCUCr;

    _IPP_CHECK_ARG(NULL!=pSrcBGR);
    _IPP_CHECK_ARG((24<=srcStep) || (-24>=srcStep));
    _IPP_CHECK_ARG(NULL!=pDstMCU);
    _IPP_CHECK_ARG((NULL!=pDstMCU[0])&&(NULL!=pDstMCU[1])&&(NULL!=pDstMCU[2]));
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pDstMCU[0]));
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pDstMCU[1]));
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pDstMCU[2]));

    pDstMCUY =pDstMCU[0];
    pDstMCUCb=pDstMCU[1];
    pDstMCUCr=pDstMCU[2];

    for (j=8; j>0; j--) {

        /* Calculate Ys for pixels 0-7 */
        pDstMCUY[0] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[ 0]), (pSrcBGR[ 1]), (pSrcBGR[ 2]));
        pDstMCUY[1] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[ 3]), (pSrcBGR[ 4]), (pSrcBGR[ 5]));
        pDstMCUY[2] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[ 6]), (pSrcBGR[ 7]), (pSrcBGR[ 8]));
        pDstMCUY[3] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[ 9]), (pSrcBGR[10]), (pSrcBGR[11]));
        pDstMCUY[4] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[12]), (pSrcBGR[13]), (pSrcBGR[14]));
        pDstMCUY[5] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[15]), (pSrcBGR[16]), (pSrcBGR[17]));
        pDstMCUY[6] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[18]), (pSrcBGR[19]), (pSrcBGR[20]));
        pDstMCUY[7] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[21]), (pSrcBGR[22]), (pSrcBGR[23]));

        /* Calculate Cbs for pixels 0-7 */
        pDstMCUCb[0] = (Ipp16s)_BGR2YCC_LS_CB((pSrcBGR[ 0]), (pSrcBGR[ 1]), (pSrcBGR[ 2]));
        pDstMCUCb[1] = (Ipp16s)_BGR2YCC_LS_CB((pSrcBGR[ 3]), (pSrcBGR[ 4]), (pSrcBGR[ 5]));
        pDstMCUCb[2] = (Ipp16s)_BGR2YCC_LS_CB((pSrcBGR[ 6]), (pSrcBGR[ 7]), (pSrcBGR[ 8]));
        pDstMCUCb[3] = (Ipp16s)_BGR2YCC_LS_CB((pSrcBGR[ 9]), (pSrcBGR[10]), (pSrcBGR[11]));
        pDstMCUCb[4] = (Ipp16s)_BGR2YCC_LS_CB((pSrcBGR[12]), (pSrcBGR[13]), (pSrcBGR[14]));
        pDstMCUCb[5] = (Ipp16s)_BGR2YCC_LS_CB((pSrcBGR[15]), (pSrcBGR[16]), (pSrcBGR[17]));
        pDstMCUCb[6] = (Ipp16s)_BGR2YCC_LS_CB((pSrcBGR[18]), (pSrcBGR[19]), (pSrcBGR[20]));
        pDstMCUCb[7] = (Ipp16s)_BGR2YCC_LS_CB((pSrcBGR[21]), (pSrcBGR[22]), (pSrcBGR[23]));

        /* Calculate Crs for pixels 0-7 */
        pDstMCUCr[0] = (Ipp16s)_BGR2YCC_LS_CR((pSrcBGR[ 0]), (pSrcBGR[ 1]), (pSrcBGR[ 2]));
        pDstMCUCr[1] = (Ipp16s)_BGR2YCC_LS_CR((pSrcBGR[ 3]), (pSrcBGR[ 4]), (pSrcBGR[ 5]));
        pDstMCUCr[2] = (Ipp16s)_BGR2YCC_LS_CR((pSrcBGR[ 6]), (pSrcBGR[ 7]), (pSrcBGR[ 8]));
        pDstMCUCr[3] = (Ipp16s)_BGR2YCC_LS_CR((pSrcBGR[ 9]), (pSrcBGR[10]), (pSrcBGR[11]));
        pDstMCUCr[4] = (Ipp16s)_BGR2YCC_LS_CR((pSrcBGR[12]), (pSrcBGR[13]), (pSrcBGR[14]));
        pDstMCUCr[5] = (Ipp16s)_BGR2YCC_LS_CR((pSrcBGR[15]), (pSrcBGR[16]), (pSrcBGR[17]));
        pDstMCUCr[6] = (Ipp16s)_BGR2YCC_LS_CR((pSrcBGR[18]), (pSrcBGR[19]), (pSrcBGR[20]));
        pDstMCUCr[7] = (Ipp16s)_BGR2YCC_LS_CR((pSrcBGR[21]), (pSrcBGR[22]), (pSrcBGR[23]));

        /* Update the pointers to output Y, Cb, Cr for next row */
        pDstMCUY  += 8;
        pDstMCUCb += 8;
        pDstMCUCr += 8;

        /* Update the pointer to input BGR  data of the next row */
        pSrcBGR += srcStep;

    } /* for (j=0; j<IPPJPEG_BLOCKSIZE; j++) */

    return IPP_STATUS_OK;
}

/******************************************************************************
// Name:             ippiBGRToYCbCr422LS_MCU_8u16s_C3P3
// Description:      Converts MCU from BGR to YCbCr422. The size is 16x8.
// Input Arguments: 
//          pSrcBGR: Identifies input image data buffer. It was sorted block by bock.
//          srcStep: Specifies the number of bytes in a line of the source image. 
//
// Output Arguments:
//       pDstMCU[3]: Identifies three pointer array. 
//                   pSrcMCU[0] point to Y  block.
//                   pSrcMCU[1] point to Cb block.
//                   pSrcMCU[2] point to Cr block.
//                  
// Remarks:      
//                   1. The start address of each "pDstMCU[]" shall be aligned at 4byte boundary.
//                   2. It is better to do this alignment at 32byte boundary to optimize 
//                      D-Cache accessing.
//                   
// Returns:         
//    IPP_STATUS_OK: Succeeds.
//
******************************************************************************/
IPPFUN(IppStatus, ippiBGRToYCbCr422LS_MCU_8u16s_C3P3)  (const Ipp8u * pSrcBGR, 
							                            int srcStep, 
       									                Ipp16s * pDstMCU[3])
{
    int i, j;
    int b, g, r;
    int nOffset;  
    Ipp16s * pDstMCUY;
    Ipp16s * pDstMCUCb;
    Ipp16s * pDstMCUCr;

    _IPP_CHECK_ARG(NULL!=pSrcBGR);
    _IPP_CHECK_ARG((24<=srcStep) || (-24>=srcStep));
    _IPP_CHECK_ARG(NULL!=pDstMCU);
    _IPP_CHECK_ARG((NULL!=pDstMCU[0])&&(NULL!=pDstMCU[1])&&(NULL!=pDstMCU[2]));
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pDstMCU[0]));
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pDstMCU[1]));
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pDstMCU[2]));

    pDstMCUY =pDstMCU[0];
    pDstMCUCb=pDstMCU[1];
    pDstMCUCr=pDstMCU[2];

    nOffset=8*srcStep-24;

    for (i=2; i>0; i--) {
        for (j=8; j>0; j--) {
            /* Calculate Ys for pixels 0-7 */
            pDstMCUY[0] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[ 0]), (pSrcBGR[ 1]), (pSrcBGR[ 2]));
            pDstMCUY[1] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[ 3]), (pSrcBGR[ 4]), (pSrcBGR[ 5]));
            pDstMCUY[2] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[ 6]), (pSrcBGR[ 7]), (pSrcBGR[ 8]));
            pDstMCUY[3] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[ 9]), (pSrcBGR[10]), (pSrcBGR[11]));
            pDstMCUY[4] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[12]), (pSrcBGR[13]), (pSrcBGR[14]));
            pDstMCUY[5] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[15]), (pSrcBGR[16]), (pSrcBGR[17]));
            pDstMCUY[6] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[18]), (pSrcBGR[19]), (pSrcBGR[20]));
            pDstMCUY[7] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[21]), (pSrcBGR[22]), (pSrcBGR[23]));

            /* Accumulate pixels 0 and 1 for subsampling */
            b = (int)pSrcBGR[ 0] + (int)pSrcBGR[ 3];
            g = (int)pSrcBGR[ 1] + (int)pSrcBGR[ 4];
            r = (int)pSrcBGR[ 2] + (int)pSrcBGR[ 5];
            /* Calculate average Cb and Cr for pixel group 0 */
            pDstMCUCb[0] = (Ipp16s)_BGR2YCC422_LS_CB(b, g, r);
            pDstMCUCr[0] = (Ipp16s)_BGR2YCC422_LS_CR(b, g, r);

            /* Accumulate pixels 2 and 3 for subsampling */
            b = (int)pSrcBGR[ 6] + (int)pSrcBGR[ 9];
            g = (int)pSrcBGR[ 7] + (int)pSrcBGR[10];
            r = (int)pSrcBGR[ 8] + (int)pSrcBGR[11];
            /* Calculate average Cb and Cr for pixel group 1 */
            pDstMCUCb[1] = (Ipp16s)_BGR2YCC422_LS_CB(b, g, r);
            pDstMCUCr[1] = (Ipp16s)_BGR2YCC422_LS_CR(b, g, r);

            /* Accumulate pixels 4 and 5 for subsampling */
            b = (int)pSrcBGR[12] + (int)pSrcBGR[15];
            g = (int)pSrcBGR[13] + (int)pSrcBGR[16];
            r = (int)pSrcBGR[14] + (int)pSrcBGR[17];
            /* Calculate average Cb and Cr for pixel group 2 */
            pDstMCUCb[2] = (Ipp16s)_BGR2YCC422_LS_CB(b, g, r);
            pDstMCUCr[2] = (Ipp16s)_BGR2YCC422_LS_CR(b, g, r);

            /* Accumulate pixels 6 and 7 for subsampling */
            b = (int)pSrcBGR[18] + (int)pSrcBGR[21];
            g = (int)pSrcBGR[19] + (int)pSrcBGR[22];
            r = (int)pSrcBGR[20] + (int)pSrcBGR[23];
            /* Calculate average Cb and Cr for pixel group 3 */
            pDstMCUCb[3] = (Ipp16s)_BGR2YCC422_LS_CB(b, g, r);
            pDstMCUCr[3] = (Ipp16s)_BGR2YCC422_LS_CR(b, g, r);

            /* Update the pointers to output Y, Cb, Cr for next row */
            pDstMCUY  += 8;
            pDstMCUCb += 8;
            pDstMCUCr += 8;

            /* Update the pointer to input BGR  data of the next row */
            pSrcBGR += srcStep;

        } /* for (j=0; j<8; j++) */
        pSrcBGR-=(nOffset);
        pDstMCUCb -= 60;
        pDstMCUCr -= 60;
    }

    return IPP_STATUS_OK;
}

/******************************************************************************
// Name:             ippiBGRToYCbCr411LS_MCU_8u16s_C3P3
// Description:      Converts MCU from BGR to YCbCr411. The size is 16x16.
// Input Arguments: 
//          pSrcBGR: Identifies input image data buffer. It was sorted block by bock.
//          srcStep: Specifies the number of bytes in a line of the source image. 
//
// Output Arguments:
//       pDstMCU[3]: Identifies three pointer array. 
//                   pSrcMCU[0] point to Y  block.
//                   pSrcMCU[1] point to Cb block.
//                   pSrcMCU[2] point to Cr block.
//                  
// Remarks:      
//                   1. The start address of each "pDstMCU[]" shall be aligned at 4byte boundary.
//                   2. It is better to do this alignment at 32byte boundary to optimize 
//                      D-Cache accessing.
//                   
// Returns:         
//    IPP_STATUS_OK: Succeeds.
//
******************************************************************************/
IPPFUN(IppStatus, ippiBGRToYCbCr411LS_MCU_8u16s_C3P3)  (const Ipp8u * pSrcBGR, 
							                            int srcStep, 
       									                Ipp16s * pDstMCU[3])
{
    int i, j;
    int b, g, r;
    int nOffset;
    int inpR[4], inpG[4], inpB[4];
    Ipp16s * pDstMCUY;
    Ipp16s * pDstMCUCb;
    Ipp16s * pDstMCUCr;

    _IPP_CHECK_ARG(NULL!=pSrcBGR);
    _IPP_CHECK_ARG((24<=srcStep) || (-24>=srcStep));
    _IPP_CHECK_ARG(NULL!=pDstMCU);
    _IPP_CHECK_ARG((NULL!=pDstMCU[0])&&(NULL!=pDstMCU[1])&&(NULL!=pDstMCU[2]));
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pDstMCU[0]));
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pDstMCU[1]));
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pDstMCU[2]));

    pDstMCUY =pDstMCU[0];
    pDstMCUCb=pDstMCU[1];
    pDstMCUCr=pDstMCU[2];

    nOffset = 8*srcStep-24;

    for (i=4; i>0; i--) {

        /* Two rows (start from the even row) are processed in every loop */
        for (j=8; j>0; j-=2) {

            /* Calculate Ys for pixels 0-7 of the even row */
            pDstMCUY[0] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[ 0]), (pSrcBGR[ 1]), (pSrcBGR[ 2]));
            pDstMCUY[1] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[ 3]), (pSrcBGR[ 4]), (pSrcBGR[ 5]));
            pDstMCUY[2] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[ 6]), (pSrcBGR[ 7]), (pSrcBGR[ 8]));
            pDstMCUY[3] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[ 9]), (pSrcBGR[10]), (pSrcBGR[11]));
            pDstMCUY[4] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[12]), (pSrcBGR[13]), (pSrcBGR[14]));
            pDstMCUY[5] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[15]), (pSrcBGR[16]), (pSrcBGR[17]));
            pDstMCUY[6] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[18]), (pSrcBGR[19]), (pSrcBGR[20]));
            pDstMCUY[7] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[21]), (pSrcBGR[22]), (pSrcBGR[23]));

            /* Accumulate pixels 0 and 1 of the even row for further calculation */
            inpB[0] = ((int)pSrcBGR[ 0]) + ((int)pSrcBGR[ 3]);
            inpG[0] = ((int)pSrcBGR[ 1]) + ((int)pSrcBGR[ 4]);
            inpR[0] = ((int)pSrcBGR[ 2]) + ((int)pSrcBGR[ 5]);

            /* Accumulate pixels 2 and 3 of the even row for further calculation */
            inpB[1] = ((int)pSrcBGR[ 6]) + ((int)pSrcBGR[ 9]);
            inpG[1] = ((int)pSrcBGR[ 7]) + ((int)pSrcBGR[10]);
            inpR[1] = ((int)pSrcBGR[ 8]) + ((int)pSrcBGR[11]);

            /* Accumulate pixels 4 and 5 of the even row for further calculation */
            inpB[2] = ((int)pSrcBGR[12]) + ((int)pSrcBGR[15]);
            inpG[2] = ((int)pSrcBGR[13]) + ((int)pSrcBGR[16]);
            inpR[2] = ((int)pSrcBGR[14]) + ((int)pSrcBGR[17]);

            /* Accumulate pixels 6 and 7 of the even row for further calculation */
            inpB[3] = ((int)pSrcBGR[18]) + ((int)pSrcBGR[21]);
            inpG[3] = ((int)pSrcBGR[19]) + ((int)pSrcBGR[22]);
            inpR[3] = ((int)pSrcBGR[20]) + ((int)pSrcBGR[23]);

             /* Update the pointer to the output Y for the odd row */
            pDstMCUY += 8;

            /* Update the pointer to input BGR data of the next row (i.e., the odd row) */
            pSrcBGR += srcStep;

            /* Calculate Ys for pixels 0-7 of the odd row */
            pDstMCUY[0] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[ 0]), (pSrcBGR[ 1]), (pSrcBGR[ 2]));
            pDstMCUY[1] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[ 3]), (pSrcBGR[ 4]), (pSrcBGR[ 5]));
            pDstMCUY[2] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[ 6]), (pSrcBGR[ 7]), (pSrcBGR[ 8]));
            pDstMCUY[3] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[ 9]), (pSrcBGR[10]), (pSrcBGR[11]));
            pDstMCUY[4] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[12]), (pSrcBGR[13]), (pSrcBGR[14]));
            pDstMCUY[5] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[15]), (pSrcBGR[16]), (pSrcBGR[17]));
            pDstMCUY[6] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[18]), (pSrcBGR[19]), (pSrcBGR[20]));
            pDstMCUY[7] = (Ipp16s)_BGR2YCC_LS_Y((pSrcBGR[21]), (pSrcBGR[22]), (pSrcBGR[23]));

            /* Accumulate pixels 0 and 1 of both rows for subsampling */
            b = inpB[0] + ((int)pSrcBGR[ 0]) + ((int)pSrcBGR[ 3]);
            g = inpG[0] + ((int)pSrcBGR[ 1]) + ((int)pSrcBGR[ 4]);
            r = inpR[0] + ((int)pSrcBGR[ 2]) + ((int)pSrcBGR[ 5]);

            /* Calculate average Cb and Cr for pixel group 0 */
            pDstMCUCb[0] = (Ipp16s)_BGR2YCC411_LS_CB(b, g, r);
            pDstMCUCr[0] = (Ipp16s)_BGR2YCC411_LS_CR(b, g, r);

            /* Accumulate pixels 2 and 3 of both rows for subsampling */
            b = inpB[1] + ((int)pSrcBGR[ 6]) + ((int)pSrcBGR[ 9]);
            g = inpG[1] + ((int)pSrcBGR[ 7]) + ((int)pSrcBGR[10]);
            r = inpR[1] + ((int)pSrcBGR[ 8]) + ((int)pSrcBGR[11]);

            /* Calculate average Cb and Cr for pixel group 1 */
            pDstMCUCb[1] = (Ipp16s)_BGR2YCC411_LS_CB(b, g, r);
            pDstMCUCr[1] = (Ipp16s)_BGR2YCC411_LS_CR(b, g, r);

            /* Accumulate pixels 4 and 5 of both rows for subsampling */
            b = inpB[2] + ((int)pSrcBGR[12]) + ((int)pSrcBGR[15]);
            g = inpG[2] + ((int)pSrcBGR[13]) + ((int)pSrcBGR[16]);
            r = inpR[2] + ((int)pSrcBGR[14]) + ((int)pSrcBGR[17]);

            /* Calculate average Cb and Cr for pixel group 2 */
            pDstMCUCb[2] = (Ipp16s)_BGR2YCC411_LS_CB(b, g, r);
            pDstMCUCr[2] = (Ipp16s)_BGR2YCC411_LS_CR(b, g, r);

            /* Accumulate pixels 6 and 7 of both rows for subsampling */
            b = inpB[3] + ((int)pSrcBGR[18]) + ((int)pSrcBGR[21]);
            g = inpG[3] + ((int)pSrcBGR[19]) + ((int)pSrcBGR[22]);
            r = inpR[3] + ((int)pSrcBGR[20]) + ((int)pSrcBGR[23]);

            /* Calculate average Cb and Cr for pixel group 3 */
            pDstMCUCb[3] = (Ipp16s)_BGR2YCC411_LS_CB(b, g, r);
            pDstMCUCr[3] = (Ipp16s)_BGR2YCC411_LS_CR(b, g, r);

            /* Update the pointers to output Y, Cb, Cr for next loop */
            pDstMCUY  += 8;
            pDstMCUCb += 8;
            pDstMCUCr += 8;

            /* Update the pointer to input BGR  data of the next row */
            pSrcBGR += srcStep;

        } /* for (j=0; j<IPPJPEG_BLOCKSIZE; j+=2) */
        if (3==i) {
            pSrcBGR-=24;
            pDstMCUCb -= 4;
            pDstMCUCr -= 4;
        } else {
            pSrcBGR-=(nOffset);
            pDstMCUCb -= 28;
            pDstMCUCr -= 28;
        }
    }

    return IPP_STATUS_OK;
}

/* EOF */
